package org.news.web.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.common.redis.utils.RedisUtils;
import org.news.web.domain.News;
import org.news.web.domain.Users;
import org.news.web.mapper.NewsMapper;
import org.news.web.mapper.UsersMapper;
import org.news.web.redis.RedisConstant;
import org.springframework.stereotype.Service;
import org.news.web.domain.bo.LikesBo;
import org.news.web.domain.vo.LikesVo;
import org.news.web.domain.Likes;
import org.news.web.mapper.LikesMapper;
import org.news.web.service.ILikesService;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 点赞功能Service业务层处理
 *
 * @author Gu Ci
 * @date 2024-04-03
 */
@RequiredArgsConstructor
@Service
public class LikesServiceImpl implements ILikesService {

    private final LikesMapper baseMapper;

    private final UsersMapper usersMapper;

    private final NewsMapper newsMapper;

    /**
     * 查询点赞功能
     */
    @Override
    public LikesVo queryById(Long likeId){
        return baseMapper.selectVoById(likeId);
    }

    /**
     * 查询点赞功能列表
     */
    @Override
    public TableDataInfo<LikesVo> queryPageList(LikesBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<Likes> lqw = buildQueryWrapper(bo);
        Page<LikesVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        /**
         * 获取用户名称
         */
        if(ObjectUtil.isNotNull(result.getRecords()) && result.getRecords().size() >0){
            Set<Long> collect = result.getRecords().stream().map(item -> {
                return item.getUserId();
            }).collect(Collectors.toSet());

            List<Users> users = usersMapper.selectList(new LambdaQueryWrapper<Users>().in(Users::getUserId, collect));
            users.forEach(user ->{
                result.getRecords().stream().forEach(item ->{
                    if(item.getUserId() == user.getUserId()){
                        item.setUsername(user.getUsername());
                    }
                });
            });
        }
        /**
         * 获取新闻标题
         */
        if(ObjectUtil.isNotNull(result.getRecords()) && result.getRecords().size() >0){
            Set<Long> collect = result.getRecords().stream().map(item -> {
                return item.getNewsId();
            }).collect(Collectors.toSet());
            List<News> news = newsMapper.selectList(new LambdaQueryWrapper<News>().in(News::getNewsId, collect));

            news.stream().forEach(New->{
                result.getRecords().forEach(item ->{
                    if(New.getNewsId() == item.getNewsId()){
                        item.setTitle(New.getTitle());
                    }
                });
            });
        }
        return TableDataInfo.build(result);
    }

    /**
     * 查询点赞功能列表
     */
    @Override
    public List<LikesVo> queryList(LikesBo bo) {
        LambdaQueryWrapper<Likes> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<Likes> buildQueryWrapper(LikesBo bo) {



        LambdaQueryWrapper<Likes> lqw = Wrappers.lambdaQuery();


        Set<Long> userIds = null;
        if(StringUtils.isNotBlank(bo.getUsername())){
            List<Users> username = usersMapper.selectList(new QueryWrapper<Users>().like("username", bo.getUsername()));
            if(ObjectUtil.isNotNull(username) && username.size() >0){
                userIds = username.stream().map(Users::getUserId).collect(Collectors.toSet());
            }else{
//                查询不到用户 给一个查不到的id
                userIds = new HashSet<>();
                userIds.add(-1l);
            }
        }
        lqw.in(userIds!= null, Likes::getUserId, userIds);
        return lqw;
    }

    /**
     * 新增点赞功能
     */
    @Override
    public Boolean insertByBo(LikesBo bo) {
        Likes add = MapstructUtils.convert(bo, Likes.class);

        return like(bo.getUserId(), bo.getNewsId())>0;
    }

    /**
     * 修改点赞功能
     */
    @Override
    public Boolean updateByBo(LikesBo bo) {
        Likes update = MapstructUtils.convert(bo, Likes.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(Likes entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除点赞功能
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {

        String key = RedisConstant.NEWS_PRE_KEY +":"+RedisConstant.LIKE_PRE_KEY+":";
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
//        删除缓存
        ids.forEach(
            item->{
                Likes likes = baseMapper.selectById(item);
                //删除缓存
                RedisUtils.delSetOne(key+likes.getNewsId(),likes.getUserId());
                //3.删除行为数据缓存
                RedisUtils.setCacheMapValue(RedisConstant.XIN_WEI + ":" + likes.getUserId() + ":" + likes.getNewsId(),RedisConstant.IS_LIKE,0);
            }
        );
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public int like(Long userId,Long newsId) {
        String key = RedisConstant.NEWS_PRE_KEY +":"+RedisConstant.LIKE_PRE_KEY+":"+newsId;
        // 同步缓存进行处理  用于后台
        // 1.查询缓存是否该用户已经点过赞点赞
        if (isLike(userId,newsId)) {
//            点过赞就不需要重新点了
            throw new ServiceException("该用户已经点过赞了");
        }
        //2.添加缓存信息
        boolean b = RedisUtils.addCacheSet(key, userId);
        System.out.println("缓存信息添加："+b);
//        3.添加行为数据缓存
        String XINWEN_KEY = RedisConstant.XIN_WEI + ":" + userId + ":" + newsId;
        RedisUtils.setCacheMapValue(XINWEN_KEY,RedisConstant.IS_LIKE,1);


        //3.数据库中进行添加
        Likes likes = new Likes();
        likes.setUserId(userId);
        likes.setNewsId(newsId);
        baseMapper.insert(likes);
        return 1;
    }

    @Override
    public int nolike(Long userId,Long newsId) {
        String key = RedisConstant.NEWS_PRE_KEY +":"+RedisConstant.LIKE_PRE_KEY+":"+newsId;
        // 同步缓存进行处理 用于后台
//        1.查询缓存是否该用户已经点过赞点赞
        if (!isLike(userId,newsId)) {
            throw new ServiceException("该用户没有点赞无法取消");
        }
//        删除redis中的用户信息
        boolean b = RedisUtils.delSetOne(key, userId);
        System.out.println("缓存信息删除："+b);
//        3.添加行为数据缓存
        String XINWEN_KEY = RedisConstant.XIN_WEI + ":" + userId + ":" + newsId;
        RedisUtils.setCacheMapValue(XINWEN_KEY,RedisConstant.IS_LIKE,0);
//        删除数据库数据保存同步
        baseMapper.delete(new LambdaQueryWrapper<Likes>().eq(Likes::getUserId,userId).eq(Likes::getNewsId,newsId));
        return 1;
    }

    @Override
    public boolean isLike(Long userId, Long newsId){
        String key = RedisConstant.NEWS_PRE_KEY +":"+RedisConstant.LIKE_PRE_KEY+":"+newsId;
        return RedisUtils.isContains(key,userId);
    }


}
